package com.oauth2.demo.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;

import com.oauth2.demo.model.ReceiveMessage;

import com.oauth2.demo.model.WeixinQrCode;
import com.oauth2.demo.model.WxUser;
import com.oauth2.demo.utils.LocalCacheUtil;
import com.oauth2.demo.utils.WeixinApiUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController
public class OauthController {

    //redirect_uri地址必须==idm应用里面的callback地址,redirect_url可以携带参数
    private static String BASE_URL = "http://192.168.219.139";
    private String AUTHORIZE_URL = BASE_URL + "/esc-sso/oauth2.0/authorize";
    private String TOKEN_URL = BASE_URL + "/esc-sso/oauth2.0/accessToken";
    private static String USER_INFO_URL = BASE_URL + "/esc-sso/oauth2.0/profile";
    //登出地址
    private static String LOGOUT_URL = BASE_URL + "/esc-sso/logout?service=http://127.0.0.1:8080/login";
    //回调地址
    private String REDIRECT_URI = "http://127.0.0.1:8080/oauth/callback";
    private String WX_REDIRECT_URI = "http://435c1642.r16.cpolar.top/wxCallback";

    @Resource
    private WeixinApiUtil weixinApiUtil;

    @GetMapping(value = "/wx/qrcode")
    public WeixinQrCode wxQrcode(HttpServletRequest request) throws IOException {

        String uuid = request.getParameter("uuid");
        WeixinQrCode qrCode = weixinApiUtil.getQrCode(uuid);

        return qrCode;

    }


    @GetMapping(value = "/login/wxcheck")
    public String WxLoginPage(HttpServletRequest request) throws IOException {
        String echostr = request.getParameter("echostr");
        return echostr;

    }

    @PostMapping(value = "/login/wxcheck")
    public String wxCallback(@RequestBody String requestBody, @RequestParam("signature") String signature,
                            @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce) throws JsonProcessingException {

        log.debug("requestBody:{}", requestBody);
        log.debug("signature:{}", signature);
        log.debug("timestamp:{}", timestamp);
        log.debug("nonce:{}", nonce);

        Map<String, Object> map = XmlUtil.xmlToMap(requestBody);
        System.out.println(map);


        ReceiveMessage receiveMessage = new ReceiveMessage();
        receiveMessage.setToUserName((String)map.get("ToUserName"));
        receiveMessage.setFromUserName((String)map.get("FromUserName"));
        receiveMessage.setCreateTime((String)map.get("CreateTime"));
        receiveMessage.setMsgType((String)map.get("MsgType"));
        receiveMessage.setContent((String)map.get("Content"));
        receiveMessage.setMsgId((String)map.get("MsgId"));
        receiveMessage.setEvent((String) map.get("Event"));
        receiveMessage.setTicket((String)map.get("Ticket"));

// 写入本地缓存
        WxUser wxUser = new WxUser();
        wxUser.setNickName((String)map.get("ToUserName"));
        wxUser.setOpenid((String)map.get("FromUserName"));
        String uuid = (String)map.get("EventKey");
        LocalCacheUtil.put(uuid,wxUser);

        // 扫码登录
        if (StrUtil.isNotEmpty(receiveMessage.getTicket())){
            String response = handleScanLogin(receiveMessage);
            return response;
        }


//        // 关注
//        if (WeixinMsgUtil.isEventAndSubscribe(receiveMessage)) {
//            return receiveMessage.getReplyTextMsg("欢迎关注【程序猿阿朗】公众号");
//        }
//        return receiveMessage.getReplyTextMsg("收到（自动回复）");
        return "登录成功";

    }



    private String handleScanLogin(ReceiveMessage receiveMessage) {
        String qrCodeTicket = receiveMessage.getTicket();
        String openId = receiveMessage.getFromUserName();
        return receiveMessage.getReplyTextMsg("你已成功登录！");
    }

    @GetMapping(value = "/wxLogin")
    @ResponseBody
    public void WxLoginPage(HttpServletRequest request, HttpServletResponse response) throws IOException {

        String uuid = request.getParameter("uuid");
        System.out.println(uuid);
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxe6ea8c68910ea0a2&redirect_uri="
                + WX_REDIRECT_URI + "&response_type=code&scope=snsapi_userinfo&state=" + uuid + "#wechat_redirect";
        response.setContentType("image/png");
        QrCodeUtil.generate(url, 300, 300, "jpg", response.getOutputStream());

    }
    @RequestMapping(value = "/wxCallback")
    @ResponseBody
    public String pcCallback(String code, String state, HttpServletRequest request, HttpServletResponse response) throws IOException {

        System.out.println(state);

        WxUser userInfo = weixinApiUtil.getUserInfo(code);

        // 写入本地缓存

        LocalCacheUtil.put(state, userInfo);

        return "登录成功";
//        ModelAndView mav = new ModelAndView();
//        mav.addObject("accountNo", "哈哈哈哈");
//        mav.setViewName("oauthSuccessIndex");
//        return mav;
    }
    @RequestMapping(value = "/getUser")
    @ResponseBody
    public WxUser getUser(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String uuid = request.getParameter("uuid");
        System.out.println(uuid);

        // 写入本地缓存
        WxUser userInfo = (WxUser) LocalCacheUtil.get(uuid);
        return userInfo;
    }


    @RequestMapping(value = "/login")
    public ModelAndView login(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        ModelAndView mav = new ModelAndView();
        if (request.getParameter("code") == null) {
            String url = AUTHORIZE_URL +
                    "?client_id=" + getClientID() +
                    "&redirect_uri=" + getURLEncoderString(REDIRECT_URI) +
                    "&response_type=code" +
                    "&oauth_timestamp=" + getTimeTamp();
            log.debug("第一次浏览器重定向请求Oauth服务器地址，:{}", url);
            mav.setViewName("redirect:" + url); // 获取处理oauth的请求地址
        } else {
            String code = request.getParameter("code");
            Map<String, Object> tokenMap = new HashMap<String, Object>();
            tokenMap.put("grant_type", "authorization_code");
            tokenMap.put("oauth_timestamp", getTimeTamp());
            tokenMap.put("client_id", getClientID());
            tokenMap.put("client_secret", getClientSecret());
            //不需要转义
            tokenMap.put("redirect_uri", REDIRECT_URI);
            tokenMap.put("code", code);
            log.debug("第二次请求Oauth服务器地址,获取Token数据:{},请求参数:{}", TOKEN_URL, JSON.toJSONString(tokenMap));
            String tokenResult = HttpUtil.post(TOKEN_URL, tokenMap);
            log.debug("第二次请求Oauth服务器响应结果:{}", tokenResult);
            JSONObject obj2 = JSON.parseObject(tokenResult);
            String userResult = HttpUtil.get(USER_INFO_URL + "?access_token=" + obj2.getString("access_token"));
            log.debug("第三次获取用户信息结果:{}", userResult);
            JSONObject obj = JSON.parseObject(userResult);
            String accountNo = JSON.parseObject(obj.getString("attributes")).getString("account_no");
            request.getSession().setAttribute("responseData", userResult);
            request.getSession().setAttribute("accountNo", accountNo);
            mav.addObject("accountNo", accountNo);
            mav.setViewName("redirect:/index");
        }
        return mav;
    }

    @RequestMapping(value = "/logout")
    public ModelAndView logout(HttpServletRequest request, HttpServletResponse response) {
        request.getSession().setAttribute("accountNo", "");
        ModelAndView mav = new ModelAndView();
        mav.setViewName("redirect:" + LOGOUT_URL); // 获取处理oauth的请求地址
        return mav;
    }

    @RequestMapping("/index")
    public ModelAndView test(HttpServletRequest request) {

        ModelAndView modelAndView = new ModelAndView();
        String accountNo = (String) request.getSession().getAttribute("accountNo");
        String responseData = (String) request.getSession().getAttribute("responseData");
        modelAndView.addObject("accountNo", accountNo);
        modelAndView.addObject("responseData", responseData);
        modelAndView.setViewName("index"); // 获取处理oauth的请求地址
        log.debug("进入测试方法oauthIndex。。。。。。");
        return modelAndView;
    }

    @RequestMapping("/userinfo")
    public ModelAndView user(HttpServletRequest request) {

        ModelAndView modelAndView = new ModelAndView();
        String uuid = request.getParameter("uuid");
        WxUser wxUser = (WxUser)LocalCacheUtil.get(uuid);
        modelAndView.addObject("nickName", wxUser.getNickName());
        modelAndView.setViewName("user");

        return modelAndView;
    }

    /*
    http://oauth.ebuy.city:8080/test/oauth/#/callback?code=OC-60-FfrRwEdgDwRzs54GwP5bkRXDZytNZ1mGzyR*/
    @RequestMapping("/oauth/callback")
    public ModelAndView callback(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("oauthIndex"); // 获取处理oauth的请求地址
        log.debug("进入测试方法oauthCallback,请求url:{}", request.getRequestURL().toString());
        ModelAndView login = login(request, response);
        return login;
    }


    private static String getClientID() {
        return "0d65c902eed097436628";
    }

    private static String getClientSecret() {
        return "e4bb88774125d14afd480e492684d2489b3a";
    }

    public static String getURLEncoderString(String str) {
        String result = "";
        if (null == str) {
            return "";
        }
        try {
            result = java.net.URLEncoder.encode(str, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

    private String getTimeTamp() {
        return String.valueOf(System.currentTimeMillis());
    }
}
